﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ZBJF.Warranty.Common.Common
{
    public class WebApiCaller
    {
        public WebApiCaller()
        {
            //todo 从webconfig中读取
            ApiEncoding = Encoding.UTF8;
            Method = "POST";
            AppId = "";
            Secret = "";
        }

        public WebApiCaller(Encoding apiEncoding)
        {
            ApiEncoding = apiEncoding;
        }

        private Encoding ApiEncoding { get; set; }
        private string Method { get; set; }

        public string AppId { get; set; }
        public string Secret { get; set; }
        public string Get(string url, string jsonData)
        {
            Method = "GET";
            return GetDataFormUrl(url, jsonData);
        }

        public string Post(string url, string jsonData)
        {
            Method = "POST";
            return GetDataFormUrl(url, jsonData);
        }

        private string GetDataFormUrl(string url, string jsonData)
        {
            string retString;
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = Method;

                request.Accept = "application/json";
                request.ContentType = "application/json;charset=utf8";

                request.ContentLength = Encoding.UTF8.GetBytes(jsonData).Length;

                //这个在Post的时候，一定要加上，如果服务器返回错误，他还会继续再去请求，不会使用之前的错误数据，做返回数据
                request.ServicePoint.Expect100Continue = false;

                Stream myRequestStream = null;
                try
                {
                    myRequestStream = request.GetRequestStream();
                    myRequestStream.Write(Encoding.UTF8.GetBytes(jsonData), 0, Encoding.UTF8.GetBytes(jsonData).Length);
                }
                catch (Exception ex)
                {

                }
                finally
                {
                    if (myRequestStream != null)
                    {
                        myRequestStream.Close();
                        myRequestStream.Dispose();
                    }
                }


                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    var responseStream = response.GetResponseStream();
                    if (responseStream != null)
                    {
                        using (StreamReader myStreamReader = new StreamReader(responseStream,
                            ApiEncoding))
                        {
                            retString = myStreamReader.ReadToEnd();
                        }
                    }
                    else
                    {
                        retString = "has no data response!";
                    }
                }

            }
            catch (Exception ex)
            {
                retString = ex.ToString();
            }

            return retString;
        }


        /// <summary>
        /// 同步GET请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public string Get(string url, Dictionary<string, string> parameters)
        {
            WebClient client = new WebClient { Encoding = Encoding.UTF8 };

            if (parameters != null)
                foreach (var pv in parameters)
                {
                    client.QueryString.Add(pv.Key, pv.Value);
                }

            string timestamp = CommonMethod.GetTimeStamp();
            client.QueryString.Add("timestamp", timestamp);

            if (!string.IsNullOrEmpty(AppId) && !string.IsNullOrEmpty(Secret))
                client.Credentials = new NetworkCredential(AppId, Secret);

            return client.DownloadString(url);

        }
        /// <summary>
        /// 异步GET请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="parameters"></param>
        /// <param name="callback"></param>
        public void AsyncGet(string url, Dictionary<string, string> parameters, Action<string> callback)
        {
            WebClient client = new WebClient { Encoding = Encoding.UTF8 };

            if (parameters != null)
                foreach (var pv in parameters)
                {
                    client.QueryString.Add(pv.Key, pv.Value);
                }

            string timestamp = CommonMethod.GetTimeStamp();

            client.QueryString.Add("timestamp", timestamp);

            if (!string.IsNullOrEmpty(AppId) && !string.IsNullOrEmpty(Secret))
                client.Credentials = new NetworkCredential(AppId, Secret);

            client.DownloadStringCompleted += client_DownloadStringCompleted;
            client.DownloadStringAsync(new Uri(url), callback);
        }

        /// <summary>
        /// 同步POST请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public string Post(string url, Dictionary<string, string> parameters)
        {
            try
            {
                WebClient client = new WebClient { Encoding = Encoding.UTF8 };

                string timestamp = CommonMethod.GetTimeStamp();

                client.QueryString.Add("timestamp", timestamp);

                if (!string.IsNullOrEmpty(AppId) && !string.IsNullOrEmpty(Secret))
                    client.Credentials = new NetworkCredential(AppId, Secret);

                NameValueCollection values = new NameValueCollection();
                if (parameters != null)
                    foreach (var kv in parameters)
                    {
                        values.Add(kv.Key, kv.Value);
                    }

                var result = client.UploadValues(url, "POST", values);
                return Encoding.UTF8.GetString(result);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message + ex.Source + ex.StackTrace + ex.InnerException);
            }
        }
        /// <summary>
        /// 异步POST请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="parameters"></param>
        /// <param name="callback"></param>
        public void AsyncPost(string url, Dictionary<string, string> parameters, Action<string> callback)
        {
            WebClient client = new WebClient { Encoding = Encoding.UTF8 };

            string timestamp = CommonMethod.GetTimeStamp();

            client.QueryString.Add("timestamp", timestamp);

            NameValueCollection values = new NameValueCollection();
            if (parameters != null)
                foreach (var kv in parameters)
                {
                    values.Add(kv.Key, kv.Value);
                }

            if (!string.IsNullOrEmpty(AppId) && !string.IsNullOrEmpty(Secret))
                client.Credentials = new NetworkCredential(AppId, Secret);

            client.UploadValuesCompleted += client_UploadValuesCompleted;
            client.UploadValuesAsync(new Uri(url), "POST", values, callback);
        }

        void client_UploadValuesCompleted(object sender, UploadValuesCompletedEventArgs e)
        {
            if (e.Result.Length > 0 && e.Error == null && e.Cancelled == false)
            {
                Action<string> obj = e.UserState as Action<string>;
                var jsonValue = Encoding.UTF8.GetString(e.Result);
                obj(jsonValue);
            }
        }

        private void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Result.Length > 0 && e.Error == null && e.Cancelled == false)
            {
                Action<string> obj = e.UserState as Action<string>;
                obj(e.Result);
            }
        }
        
        public static string GetHtmlSourceCode(string url)
        {
            var uri = new Uri(url);
            HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(uri);
            webrequest.KeepAlive = true;
            webrequest.Method = "GET";
            webrequest.ContentType = "text/html";
            webrequest.Headers.Add("Accept-Language", "en-US,en;q=0.5");
            webrequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:18.0) Gecko/20100101 Firefox/18.0";


            using (HttpWebResponse webresponse = (HttpWebResponse)webrequest.GetResponse())
            {
                using (Stream receiveStream = webresponse.GetResponseStream())
                {
                    if (receiveStream != null)
                    {
                        using (StreamReader loResponseStream = new StreamReader(receiveStream, Encoding.UTF8))
                        {
                            return loResponseStream.ReadToEnd();
                        }
                    }
                }
            }
            return string.Empty;
        }
    }
}
